package org.lanyu.springainovel.novel.controller;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.lanyu.springainovel.common.entity.TaskNotification;
import org.lanyu.springainovel.common.service.AsyncTaskWebSocketService;
import org.lanyu.springainovel.common.service.TaskNotificationService;
import org.lanyu.springainovel.common.util.UserAuthUtil;
import org.lanyu.springainovel.common.utils.TaskIdGenerator;
import org.lanyu.springainovel.common.vo.RestVO;
import org.lanyu.springainovel.novel.dto.ChapterOutlineGenerationRequest;
import org.lanyu.springainovel.novel.dto.ChapterOutlineGenerationResponse;
import org.lanyu.springainovel.novel.dto.ChapterContentGenerationRequest;
import org.lanyu.springainovel.novel.entity.ChapterContent;
import org.lanyu.springainovel.novel.service.ChapterContentService;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
import reactor.core.publisher.Flux;

import javax.validation.Valid;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;

/**
 * 章节内容控制器
 */
@Slf4j
@Tag(name = "章节内容管理", description = "章节内容的增删改查接口")
@RestController
@RequestMapping("/chapter")
@RequiredArgsConstructor
public class ChapterContentController {

    private final ChapterContentService chapterContentService;
    private final UserAuthUtil userAuthUtil;
    private final TaskNotificationService taskNotificationService;
    private final AsyncTaskWebSocketService asyncTaskWebSocketService;

    /**
     * 根据书籍ID获取所有章节
     */
    @Operation(summary = "获取书籍所有章节", description = "根据书籍ID获取所有章节信息")
    @GetMapping("/book/{bookId}")
    public RestVO<List<ChapterContent>> getChaptersByBookId(@PathVariable Long bookId) {
        java.util.List<ChapterContent> chapters = chapterContentService.getChaptersByBookId(bookId);
        return RestVO.success(chapters);
    }

    /**
     * 根据书籍ID和章节号获取章节
     */
    @Operation(summary = "获取指定章节", description = "根据书籍ID和章节号获取章节内容")
    @GetMapping("/book/{bookId}/chapter/{chapterNumber}")
    public RestVO<ChapterContent> getChapterByBookIdAndNumber(
            @PathVariable Long bookId, 
            @PathVariable Integer chapterNumber) {
        ChapterContent chapter = chapterContentService.getChapterByBookIdAndNumber(bookId, chapterNumber);
        if (chapter == null) {
            return RestVO.fail("章节不存在");
        }
        return RestVO.success(chapter);
    }

    /**
     * 根据ID获取章节
     */
    @Operation(summary = "根据ID获取章节", description = "根据章节ID获取章节详情")
    @GetMapping("/{id}")
    public RestVO<ChapterContent> getChapterById(@PathVariable Long id) {
        ChapterContent chapter = chapterContentService.getChapterById(id);
        if (chapter == null) {
            return RestVO.fail("章节不存在");
        }
        return RestVO.success(chapter);
    }

    /**
     * 创建或更新章节
     */
    @Operation(summary = "创建或更新章节", description = "创建新章节或更新现有章节")
    @PostMapping
    public RestVO<ChapterContent> saveOrUpdateChapter(@RequestBody ChapterContent chapter) {
        try {
            ChapterContent savedChapter = chapterContentService.saveOrUpdateChapter(chapter);
            return RestVO.success(savedChapter);
        } catch (Exception e) {
            return RestVO.fail("保存章节失败: " + e.getMessage());
        }
    }

    /**
     * 删除章节
     */
    @Operation(summary = "删除章节", description = "根据ID删除章节")
    @DeleteMapping("/{id}")
    public RestVO<String> deleteChapter(@PathVariable Long id) {
        try {
            boolean deleted = chapterContentService.removeById(id);
            if (deleted) {
                return RestVO.success("删除成功");
            } else {
                return RestVO.fail("删除失败，章节不存在");
            }
        } catch (Exception e) {
            return RestVO.fail("删除失败: " + e.getMessage());
        }
    }

    /**
     * 根据书籍ID分页查询章节细纲
     */
    @Operation(summary = "分页查询章节细纲", description = "根据书籍ID分页查询章节细纲信息")
    @GetMapping("/outline/book/{bookId}")
    public RestVO<Page<ChapterContent>> getChapterOutlinesByBookId(
            @PathVariable Long bookId,
            @RequestParam(defaultValue = "1") Integer pageNum,
            @RequestParam(defaultValue = "10") Integer pageSize) {
        Page<ChapterContent> chapterPage = chapterContentService.getChapterOutlinesByBookId(bookId, pageNum, pageSize);
        return RestVO.success(chapterPage);
    }

    /**
     * 生成章节细纲
     */
    @Operation(summary = "生成章节细纲", description = "根据书籍大纲生成指定章节的细纲，并保存到数据库")
    @PostMapping("/outline/generate")
    public RestVO<String> generateChapterOutlinesAsync(
            @Parameter(description = "生成章节细纲的请求参数", required = true)
            @Valid @RequestBody ChapterOutlineGenerationRequest request) {
        try {
            log.info("收到章节细纲生成请求，书籍ID: {}, 模型ID: {}, 起始章节: {}, 章节数量: {}", 
                    request.getBookId(), request.getModelId(), request.getStartChapterNumber(), request.getChapterCount());
            
            // 准备任务参数
            Map<String, Object> taskParams = new HashMap<>();
            taskParams.put("bookId", request.getBookId());
            taskParams.put("modelId", request.getModelId());
            taskParams.put("startChapterNumber", request.getStartChapterNumber());
            taskParams.put("chapterCount", request.getChapterCount());
            taskParams.put("promptTemplateId", request.getPromptTemplateId());
            
            // 生成规范的任务ID
            String taskId = TaskIdGenerator.generateSuboutlineTaskId(request.getBookId());
            
            // 获取当前用户ID
            Long userId = userAuthUtil.getRequiredCurrentUserId();
            
            // 创建任务
            ObjectMapper objectMapper = new ObjectMapper();
            String taskParamsJson = objectMapper.writeValueAsString(taskParams);
            taskNotificationService.createTask(taskId, userId, "CHAPTER_OUTLINE_GENERATION", 
                    "章节细纲生成", taskParamsJson);
            
            // 使用CompletableFuture执行异步任务
            CompletableFuture.supplyAsync(() -> {
                try {
                    // 获取书籍ID
                    Long bookId = (Long) taskParams.get("bookId");
                    String bookIdStr = bookId != null ? bookId.toString() : "unknown";
                    
                    // 更新任务状态为运行中
                    taskNotificationService.updateTaskStatus(taskId, "RUNNING", 
                            "开始生成章节细纲");
                    
                    // 使用统一消息格式发送章节细纲生成开始消息
                    asyncTaskWebSocketService.sendChapterOutlineGenerationMessage(bookIdStr, "RUNNING", 0, "开始生成章节细纲", null);
                    
                    // 创建新的请求对象
                    ChapterOutlineGenerationRequest taskRequest = new ChapterOutlineGenerationRequest();
                    taskRequest.setBookId((Long) taskParams.get("bookId"));
                    taskRequest.setModelId((Long) taskParams.get("modelId"));
                    taskRequest.setStartChapterNumber((Integer) taskParams.get("startChapterNumber"));
                    taskRequest.setChapterCount((Integer) taskParams.get("chapterCount"));
                    taskRequest.setPromptTemplateId((Long) taskParams.get("promptTemplateId"));
                    
                    // 更新进度
                    taskNotificationService.updateTaskProgress(taskId, 20, "正在分析章节大纲");
                    
                    // 使用统一消息格式发送进度更新
                    asyncTaskWebSocketService.sendChapterOutlineGenerationMessage(bookIdStr, "RUNNING", 20, "正在分析章节大纲", null);
                    
                    // 生成章节细纲
                    ChapterOutlineGenerationResponse response = chapterContentService.generateChapterOutlines(taskRequest, userId);
                    
                    // 更新进度
                    taskNotificationService.updateTaskProgress(taskId, 80, "正在保存章节细纲到数据库");
                    
                    // 使用统一消息格式发送进度更新
                    asyncTaskWebSocketService.sendChapterOutlineGenerationMessage(bookIdStr, "RUNNING", 80, "正在保存章节细纲到数据库", null);
                    
                    // 更新进度
                    taskNotificationService.updateTaskProgress(taskId, 90, "章节细纲保存完成");
                    
                    // 使用统一消息格式发送进度更新
                    asyncTaskWebSocketService.sendChapterOutlineGenerationMessage(bookIdStr, "RUNNING", 90, "章节细纲保存完成", null);
                    
                    // 更新进度
                    taskNotificationService.updateTaskProgress(taskId, 100, "章节细纲生成完成");
                    
                    // 使用统一消息格式发送完成消息
                    Map<String, Object> resultData = new HashMap<>();
                    resultData.put("bookId", bookId);
                    resultData.put("startChapterNumber", taskRequest.getStartChapterNumber());
                    resultData.put("chapterCount", taskRequest.getChapterCount());
                    resultData.put("generatedChapters", response.getChapterOutlines());
                    
                    asyncTaskWebSocketService.sendChapterOutlineGenerationMessage(bookIdStr, "COMPLETED", 100, "章节细纲生成完成", resultData);
                    
                    // 完成任务，不再返回结果数据
                    taskNotificationService.completeTask(taskId, "章节细纲生成完成");
                    
                    return null;
                } catch (Exception e) {
                    log.error("生成章节细纲失败", e);
                    
                    // 获取书籍ID
                    Long bookId = (Long) taskParams.get("bookId");
                    String bookIdStr = bookId != null ? bookId.toString() : "unknown";
                    
                    // 使用统一消息格式发送失败消息
                    asyncTaskWebSocketService.sendChapterOutlineGenerationMessage(bookIdStr, "FAILED", null, "生成章节细纲失败: " + e.getMessage(), null);
                    
                    // 标记任务失败
                    taskNotificationService.failTask(taskId, e.getMessage());
                    
                    throw new RuntimeException(e);
                }
            });
            
            log.info("章节细纲生成任务已提交，任务ID: {}", taskId);
            
            return RestVO.success(taskId);
        } catch (Exception e) {
            log.error("提交章节细纲生成任务失败", e);
            return RestVO.fail("提交章节细纲生成任务失败: " + e.getMessage());
        }
    }
    
    /**
     * 获取章节细纲任务状态
     */
    @Operation(summary = "获取任务状态", description = "获取章节细纲生成任务的状态和进度")
    @GetMapping("/outline/task/{taskId}")
    public RestVO<TaskNotification> getChapterOutlineTaskStatus(@PathVariable String taskId) {
        try {
            // 尝试直接使用taskId查询数据库
            TaskNotification task = taskNotificationService.getByTaskId(taskId);
            
            // 如果直接查询失败，尝试转换任务ID格式
            if (task == null) {
                String dbTaskId = taskId.replace("task_", "").replace("_", "");
                task = taskNotificationService.getByTaskId(dbTaskId);
            }
            
            if (task == null) {
                return RestVO.fail("任务不存在");
            }
            return RestVO.success(task);
        } catch (Exception e) {
            log.error("获取任务状态失败", e);
            return RestVO.fail("获取任务状态失败: " + e.getMessage());
        }
    }
    
    /**
     * 获取章节细纲任务结果
     */
    @Operation(summary = "获取章节细纲生成任务的状态", description = "获取章节细纲生成任务的状态")
    @Deprecated
    @GetMapping("/outline/task/{taskId}/result")
    public RestVO<String> getChapterOutlineTaskResult(@PathVariable String taskId) {
        try {
            // 尝试直接使用taskId查询数据库
            TaskNotification task = taskNotificationService.getByTaskId(taskId);
            
            // 如果直接查询失败，尝试转换任务ID格式
            if (task == null) {
                String dbTaskId = taskId.replace("task_", "").replace("_", "");
                task = taskNotificationService.getByTaskId(dbTaskId);
            }
            
            if (task == null) {
                return RestVO.fail("任务不存在");
            }
            
            // 返回任务状态
            return RestVO.success("任务状态: " + task.getStatus());
        } catch (Exception e) {
            log.error("获取任务状态失败", e);
            return RestVO.fail("获取任务状态失败: " + e.getMessage());
        }
    }
    
    /**
     * 取消章节细纲任务
     */
    @Operation(summary = "取消任务", description = "取消正在执行的章节细纲生成任务")
    @Deprecated
    @DeleteMapping("/task/{taskId}")
    public RestVO<String> cancelTask(@PathVariable String taskId) {
        try {
            // 获取当前用户ID
            Long userId = userAuthUtil.getRequiredCurrentUserId();
            
            // 获取任务信息
            TaskNotification task = taskNotificationService.getByTaskId(taskId);
            if (task == null) {
                // 尝试转换任务ID格式
                String dbTaskId = taskId.replace("task_", "").replace("_", "");
                task = taskNotificationService.getByTaskId(dbTaskId);
                if (task == null) {
                    return RestVO.fail("任务不存在");
                }
            }
            
            // 检查任务是否属于当前用户
            if (!userId.equals(task.getUserId())) {
                return RestVO.fail("无权限取消此任务");
            }
            
            // 检查任务状态
            String status = task.getStatus();
            if ("COMPLETED".equals(status) || "FAILED".equals(status) || "CANCELLED".equals(status)) {
                return RestVO.fail("任务已完成或已取消，无法取消");
            }
            
            // 取消任务
            boolean success = taskNotificationService.cancelTask(task.getTaskId());
            
            if (success) {
                return RestVO.success("任务取消成功");
            } else {
                return RestVO.fail("任务取消失败");
            }
        } catch (Exception e) {
            log.error("取消任务失败", e);
            return RestVO.fail("取消任务失败: " + e.getMessage());
        }
    }
    
    /**
     * 生成章节正文流式接口
     * @param request 生成章节正文请求
     * @return 流式响应
     */
    @PostMapping(value = "/content/generateStream", produces = MediaType.TEXT_PLAIN_VALUE + ";charset=UTF-8")
    @Operation(summary = "生成章节正文流式接口", description = "根据章节细纲生成章节正文，以流式方式返回")
    public Flux<String> generateChapterContentStream(@RequestBody ChapterContentGenerationRequest request) {
        log.info("收到生成章节正文流式请求: bookId={}, chapterNumber={}, modelId={}, systemPromptTemplateId={}", 
                request.getBookId(), request.getChapterNumber(), request.getModelId(), request.getSystemPromptTemplateId());
        
        try {
            // 获取当前用户ID
            Long userId = userAuthUtil.getRequiredCurrentUserId();
            
            // 调用服务层生成章节正文
            return chapterContentService.generateChapterContentStream(request, userId);
        } catch (Exception e) {
            log.error("生成章节正文流式接口异常", e);
            return Flux.just("生成章节正文失败: " + e.getMessage());
        }
    }
    
    /**
     * 生成章节正文异步任务接口
     * @param request 生成章节正文请求
     * @return 任务ID
     */
    @PostMapping("/content/generateAsync")
    @Operation(summary = "生成章节正文异步任务接口", description = "根据章节细纲生成章节正文，以异步任务方式执行")
    public RestVO<String> generateChapterContentAsync(@RequestBody ChapterContentGenerationRequest request) {
        try {
            log.info("收到章节正文生成异步请求: bookId={}, chapterNumber={}, modelId={}, systemPromptTemplateId={}", 
                    request.getBookId(), request.getChapterNumber(), request.getModelId(), request.getSystemPromptTemplateId());
            
            // 准备任务参数
            Map<String, Object> taskParams = new HashMap<>();
            taskParams.put("bookId", request.getBookId());
            taskParams.put("chapterNumber", request.getChapterNumber());
            taskParams.put("modelId", request.getModelId());
            taskParams.put("systemPromptTemplateId", request.getSystemPromptTemplateId());
            
            // 生成规范的任务ID
            String taskId = TaskIdGenerator.generateContentTaskId(request.getBookId(), request.getChapterNumber());
            
            // 获取当前用户ID
            Long userId = userAuthUtil.getRequiredCurrentUserId();
            
            // 检查是否有正在运行的任务
            List<TaskNotification> runningTasks = taskNotificationService.getActiveTasksByUserIdAndType(
                userId, "CHAPTER_CONTENT_GENERATION");
            if (!runningTasks.isEmpty()) {
                return RestVO.fail("已有正在运行的章节内容生成任务，请等待完成后再试");
            }
            for (TaskNotification task : runningTasks) {
                if (task.getTaskId().equals(taskId)) {
                    return RestVO.fail("已有正在运行的章节正文生成任务，请等待完成后再试");
                }
            }
            
            // 创建任务
            taskNotificationService.createTask(taskId, userId, "CHAPTER_CONTENT_GENERATION", 
                    "章节正文生成", taskParams.toString());
            
            // 使用CompletableFuture执行异步任务
            CompletableFuture.supplyAsync(() -> {
                try {
                    // 获取书籍ID和章节号
                    Long bookId = (Long) taskParams.get("bookId");
                    Integer chapterNumber = (Integer) taskParams.get("chapterNumber");
                    String bookIdStr = bookId != null ? bookId.toString() : "unknown";
                    String chapterNumberStr = chapterNumber != null ? chapterNumber.toString() : "unknown";
                    
                    // 更新任务状态为运行中
                    taskNotificationService.updateTaskStatus(taskId, "RUNNING", 
                            "开始生成章节正文");
                    
                    // 使用统一消息格式发送章节正文生成开始消息
                    asyncTaskWebSocketService.sendChapterContentGenerationMessage(bookIdStr, chapterNumberStr, "RUNNING", 0, "开始生成章节正文", null);
                    
                    // 创建新的请求对象
                    ChapterContentGenerationRequest taskRequest = new ChapterContentGenerationRequest();
                    taskRequest.setBookId((Long) taskParams.get("bookId"));
                    taskRequest.setChapterNumber((Integer) taskParams.get("chapterNumber"));
                    taskRequest.setModelId((Long) taskParams.get("modelId"));
                    taskRequest.setSystemPromptTemplateId((Long) taskParams.get("systemPromptTemplateId"));
                    
                    // 更新进度
                    taskNotificationService.updateTaskProgress(taskId, 20, "正在获取章节信息");
                    
                    // 使用统一消息格式发送进度更新
                    asyncTaskWebSocketService.sendChapterContentGenerationMessage(bookIdStr, chapterNumberStr, "RUNNING", 20, "正在获取章节信息", null);
                    
                    // 获取章节内容
                    ChapterContent chapterContent = chapterContentService.generateChapterContent(taskRequest, userId);
                    
                    // 更新进度
                    taskNotificationService.updateTaskProgress(taskId, 80, "正在保存章节正文到数据库");
                    
                    // 使用统一消息格式发送进度更新
                    asyncTaskWebSocketService.sendChapterContentGenerationMessage(bookIdStr, chapterNumberStr, "RUNNING", 80, "正在保存章节正文到数据库", null);
                    
                    // 更新进度
                    taskNotificationService.updateTaskProgress(taskId, 90, "章节正文保存完成");
                    
                    // 使用统一消息格式发送进度更新
                    asyncTaskWebSocketService.sendChapterContentGenerationMessage(bookIdStr, chapterNumberStr, "RUNNING", 90, "章节正文保存完成", null);
                    
                    // 更新进度
                    taskNotificationService.updateTaskProgress(taskId, 100, "章节正文生成完成");
                    
                    // 使用统一消息格式发送完成消息
                    Map<String, Object> resultData = new HashMap<>();
                    resultData.put("bookId", bookId);
                    resultData.put("chapterNumber", taskRequest.getChapterNumber());
                    resultData.put("chapterId", chapterContent.getId());
                    resultData.put("chapterContent", chapterContent.getContent());
                    
                    asyncTaskWebSocketService.sendChapterContentGenerationMessage(bookIdStr, chapterNumberStr, "COMPLETED", 100, "章节正文生成完成", resultData);
                    
                    // 完成任务，不再返回结果数据
                    taskNotificationService.completeTask(taskId, "章节正文生成完成");
                    
                    return null;
                } catch (Exception e) {
                    log.error("生成章节正文失败", e);
                    
                    // 获取书籍ID和章节号
                    Long bookId = (Long) taskParams.get("bookId");
                    Integer chapterNumber = (Integer) taskParams.get("chapterNumber");
                    String bookIdStr = bookId != null ? bookId.toString() : "unknown";
                    String chapterNumberStr = chapterNumber != null ? chapterNumber.toString() : "unknown";
                    
                    // 使用统一消息格式发送失败消息
                    asyncTaskWebSocketService.sendChapterContentGenerationMessage(bookIdStr, chapterNumberStr, "FAILED", null, "生成章节正文失败: " + e.getMessage(), null);
                    
                    // 标记任务失败
                    taskNotificationService.failTask(taskId, e.getMessage());
                    
                    throw new RuntimeException(e);
                }
            });
            
            log.info("章节正文生成任务已提交，任务ID: {}", taskId);
            
            return RestVO.success(taskId);
        } catch (Exception e) {
            log.error("提交章节正文生成任务失败", e);
            return RestVO.fail("提交章节正文生成任务失败: " + e.getMessage());
        }
    }
    
    /**
     * 获取章节正文任务状态
     */
    @Operation(summary = "获取章节正文任务状态", description = "获取章节正文生成任务的状态和进度")
    @GetMapping("/content/task/{taskId}")
    public RestVO<TaskNotification> getChapterContentTaskStatus(@PathVariable String taskId) {
        try {
            // 尝试直接使用taskId查询数据库
            TaskNotification task = taskNotificationService.getByTaskId(taskId);
            
            // 如果直接查询失败，尝试转换任务ID格式
            if (task == null) {
                String dbTaskId = taskId.replace("task_", "").replace("_", "");
                task = taskNotificationService.getByTaskId(dbTaskId);
            }
            
            if (task == null) {
                return RestVO.fail("任务不存在");
            }
            return RestVO.success(task);
        } catch (Exception e) {
            log.error("获取任务状态失败", e);
            return RestVO.fail("获取任务状态失败: " + e.getMessage());
        }
    }
    
    /**
     * 获取章节正文任务结果
     */
    @Operation(summary = "获取章节正文生成任务的状态", description = "获取章节正文生成任务的状态")
    @Deprecated
    @GetMapping("/content/task/{taskId}/result")
    public RestVO<String> getChapterContentTaskResult(@PathVariable String taskId) {
        try {
            // 尝试直接使用taskId查询数据库
            TaskNotification task = taskNotificationService.getByTaskId(taskId);
            
            // 如果直接查询失败，尝试转换任务ID格式
            if (task == null) {
                String dbTaskId = taskId.replace("task_", "").replace("_", "");
                task = taskNotificationService.getByTaskId(dbTaskId);
            }
            
            if (task == null) {
                return RestVO.fail("任务不存在");
            }
            
            // 返回任务状态
            return RestVO.success("任务状态: " + task.getStatus());
        } catch (Exception e) {
            log.error("获取任务状态失败", e);
            return RestVO.fail("获取任务状态失败: " + e.getMessage());
        }
    }
}